package com.learning.spring.cloud.alibaba.admin.server.security;

import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.UUID;

/**
 * ClassName: SecuritySecureConfig
 * Description: 安全配置，处理安全端点的安全性
 * Date: 2019/5/31 10:42 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Configuration(proxyBeanMethods = false)
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {

    private final AdminServerProperties adminServer;

    public SecuritySecureConfig(AdminServerProperties adminServer) {
        this.adminServer = adminServer;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        // 设置转发的地址和参数 defaultTargetUrl、targetUrlParameter
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeRequests((authorizeRequests) -> authorizeRequests
                // 授予对所有静态资产和登录页面的公共访问权。
                .antMatchers(this.adminServer.path("/assets/**")).permitAll()
                // 每个其他请求都必须经过身份验证。
                .antMatchers(this.adminServer.path("/login")).permitAll().anyRequest().authenticated())

                // 配置登录和注销。
                .formLogin((formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler))
                .logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout")))
                .httpBasic(Customizer.withDefaults())

                // 使用cookie启用CSRF-Protection
                .csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                        .ignoringRequestMatchers(
                                // 为Spring Boot管理客户端用于(取消)注册的端点禁用CSRF-Protection。
                                new AntPathRequestMatcher(this.adminServer.path("/instances"), HttpMethod.POST.toString()),
                                new AntPathRequestMatcher(this.adminServer.path("/instances/*"), HttpMethod.DELETE.toString()),

                                // 为执行器端点禁用CSRF-Protection。
                                new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))))
                .rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
    }

}